/**
 *
 * Escola
 * 22/05/2012 - 16:32:04
 *
 */
package escola.dao.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import escola.dao.AbstractDAO;

/**
 * @author Jonathan
 *
 */
public abstract class AbstractDAOImpl<T> implements AbstractDAO<T> {
	
	private @Autowired @Qualifier("sessionFactory") SessionFactory sessionFactory;
	
	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	@Override
	public T save(T entity) {
		if (entity != null) {
			getSession().saveOrUpdate(entity);
		}
		return entity;
	}

	@Override
	public Collection<T> saveAll(Collection<T> entities) {
		for (T entity : entities) {
			save(entity);
		}
		return entities;
	}

	@Override
	@SuppressWarnings("unchecked")
	public T getById(Integer id) {
		if (id != null) {
			Query query = getSession().createQuery("from " + getEntityClass().getName() + " t where t.id = ?");
			query.setInteger(0, id);
			return (T) query.uniqueResult();
		}
		return null;
	}

	@Override
	public Set<T> getByIds(int[] ids) {
		List<Integer> list = new ArrayList<Integer>(ids.length);
		for (int id : ids) {
			list.add(id);
		}
		return getByIds(list);
	}

	@Override
	public Set<T> getByIds(Integer[] ids) {
		if (ids != null) {
			List<Integer> list = new ArrayList<Integer>(ids.length);
			for (int id : ids) {
				list.add(id);
			}
			return getByIds(list);
		}
		return new HashSet<T>();
	}

	@Override
	@SuppressWarnings("unchecked")
	public Set<T> getByIds(Collection<Integer> ids) {
		if (ids != null && !ids.isEmpty()) {
			Query query = getSession().createQuery("from " + getEntityClass().getName() + " t where t.id in(:ids)");
			query.setParameterList("ids", ids);
			return new LinkedHashSet<T>(query.list());
		}
		return new HashSet<T>();
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<T> getAll() {
		Criteria criteria = getSession().createCriteria(getEntityClass());
		return criteria.list();
	}

	@Override
	@SuppressWarnings("unchecked")
	public T getByParam(String field, Object param) {
		if (!StringUtils.isBlank(field) &&  param != null) {
			Query query = getSession().createQuery("from " + getEntityClass().getName() + " t where t." + field + " = ?");
			query.setParameter(0, param);
			return (T) query.uniqueResult();
		}
		return null;
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<T> getByParamLike(String field, String param) {
		if (!StringUtils.isBlank(field) &&  param != null) {
			Query query = getSession().createQuery("from " + getEntityClass().getName() + " t where t." + field + " like ? order by t." + field);
			query.setParameter(0, "%" + param + "%");
			return query.list();
		}
		return new ArrayList<T>();
	}
	
	@Override
	public void deleteAll(Collection<T> entities) {
		for (T entity : entities) {
			delete(entity);
		}
	}

	@Override
	public void delete(T entity) {
		if (entity != null) {
			getSession().delete(entity);
		}
	}

	@Override
	public void delete(Integer id) {
		delete(getById(id));		
	}
	
	abstract protected Class<?> getEntityClass();

}
